//
//  AMapNaviFactory.m
//  flutter_plugin_gdmap
//
//  Created by xiaoka on 2021/9/27.
//

#import "AMapNaviFactory.h"
#import "MyConstant.h"
#import "FlutterPluginGdmapPlugin.h"
#import "MANaviRoute.h"
#import "CommonUtility.h"

@implementation AMapNaviFactory

- (NSObject <FlutterMessageCodec> *)createArgsCodec {
    return [FlutterStandardMessageCodec sharedInstance];
}

- (NSObject <FlutterPlatformView> *)createWithFrame:(CGRect)frame
                                     viewIdentifier:(int64_t)viewId
                                          arguments:(id _Nullable)args {
    
    AMapNavDriveView *view = [[AMapNavDriveView alloc] initWithFrame:frame
                                      viewIdentifier:viewId];
    return view;
}

@end


@implementation AMapNavDriveView {
    CGRect _frame;
    int64_t _viewId;
    FlutterMethodChannel *_channel;
    AMapNaviDriveView *_driveView;
    AMapNaviDriveManager *_driveManager;
    
    FlutterResult _result;
    
    CLLocation * _currentLocation;//最新坐标位置
    
    AMapNaviPoint *_startPoint;
    AMapNaviPoint *_endPoint;
    
}

- (instancetype)initWithFrame:(CGRect)frame
               viewIdentifier:(int64_t)viewId {
    self = [super init];
    if (self) {
        _frame = frame;
        _viewId = viewId;
        
        [self initDriveViewWithFrame:frame];
        [self initDriveManager];
        [self setup];
    }
    return self;
}

- (UIView *)view {
    return _driveView;
}


#pragma mark - Initalization
- (void)initDriveViewWithFrame:(CGRect)frame {
    _driveView = [[AMapNaviDriveView alloc] initWithFrame:frame];
    _driveView.autoresizingMask = UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight;
    _driveView.delegate = self;
    _driveView.trackingMode = AMapNaviViewTrackingModeCarNorth;
    _driveView.lineWidth = 24;
    _driveView.dashedLineWidth = 24;
    _driveView.showGreyAfterPass = YES;
    _driveView.showMoreButton = NO;
}

- (void)initDriveManager {
    _driveManager = [AMapNaviDriveManager sharedInstance];
    _driveManager.allowsBackgroundLocationUpdates = YES;
    _driveManager.pausesLocationUpdatesAutomatically = NO;
    _driveManager.isUseInternalTTS = YES;
    _driveManager.isUseInternalTTS = YES;
    
    [_driveManager addEventListener:self];
    [_driveManager addDataRepresentative:_driveView];
    
    [_driveManager setMultipleRouteNaviMode:YES];
    
}


- (void)setup {
    NSLog(@"~~~~~控件初始化");
    // channel配置
    
    _channel = [FlutterMethodChannel methodChannelWithName:[NSString stringWithFormat:@"%@%lld",
                                                            [AMAP_CHANNEL_NAME stringByAppendingString:@"/amap_navi"], _viewId]
                                           binaryMessenger:[FlutterPluginGdmapPlugin registrar].messenger];
    
    __weak __typeof__(self) weakSelf = self;
    [_channel setMethodCallHandler:^(FlutterMethodCall *call, FlutterResult result) {
        self->_result = result;
        if (weakSelf) {
            [weakSelf handleMethodCall:call result:result];
        }
    }];
    
}

- (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result {
    
    NSLog(@"~~~~~插件接收到通信Method:%@", call.method);
    //更改线路顺序
    if ([@"navigation" isEqualToString:call.method]) {
        
        NSData *pointData = [call.arguments[@"endLatlng"] dataUsingEncoding:NSUTF8StringEncoding];
        NSDictionary *pointDict = [NSJSONSerialization JSONObjectWithData:pointData
                                                                      options:NSJSONReadingMutableContainers
                                                                        error:nil];
        NSData *curLocData = [call.arguments[@"location"] dataUsingEncoding:NSUTF8StringEncoding];
        NSDictionary *curLocDict = [NSJSONSerialization JSONObjectWithData:curLocData
                                                                      options:NSJSONReadingMutableContainers
                                                                        error:nil];
        
        _startPoint = [AMapNaviPoint locationWithLatitude:[[curLocDict objectForKey:@"latitude"] doubleValue]
                                                longitude:[[curLocDict objectForKey:@"longitude"] doubleValue]];
        _endPoint = [AMapNaviPoint locationWithLatitude:[[pointDict objectForKey:@"latitude"] doubleValue]
                                                longitude:[[pointDict objectForKey:@"longitude"] doubleValue]];
        
        [_driveManager calculateDriveRouteWithStartPoints:@[_startPoint] endPoints:@[_endPoint] wayPoints:nil drivingStrategy:AMapNaviDrivingStrategyMultipleDefault];
        
        result(@"设置成功");
    } else {
        result(FlutterMethodNotImplemented);
    }
}

#pragma mark - AMapNaviDriveManagerDelegate
/**
 * @brief 驾车路径规划成功后的回调函数 since 6.1.0
 * @param driveManager 驾车导航管理类
 * @param type 路径规划类型,参考 AMapNaviRoutePlanType
 */
- (void)driveManager:(AMapNaviDriveManager *)driveManager onCalculateRouteSuccessWithType:(AMapNaviRoutePlanType)type {
    [_driveManager startGPSNavi];
}

/**
 * @brief 发生错误时,会调用代理的此方法
 * @param driveManager 驾车导航管理类
 * @param error 错误信息
 */
- (void)driveManager:(AMapNaviDriveManager *)driveManager error:(NSError *)error {
    NSLog(@"%@", error.description);
}

/**
 * @brief 驾车路径规划失败后的回调函数. 从5.3.0版本起,算路失败后导航SDK只对外通知算路失败,SDK内部不再执行停止导航的相关逻辑.因此,当算路失败后,不会收到 driveManager:updateNaviMode: 回调; AMapNaviDriveManager.naviMode 不会切换到 AMapNaviModeNone 状态, 而是会保持在 AMapNaviModeGPS or AMapNaviModeEmulator 状态.
 * @param driveManager 驾车导航管理类
 * @param error 错误信息,error.code参照 AMapNaviCalcRouteState
 */
- (void)driveManager:(AMapNaviDriveManager *)driveManager onCalculateRouteFailure:(NSError *)error {
    NSLog(@"%@", error.description);
}

/**
 * @brief 启动导航后回调函数
 * @param naviMode 导航类型，参考 AMapNaviMode .
 * @param driveManager 驾车导航管理类
 */
- (void)driveManager:(AMapNaviDriveManager *)driveManager didStartNavi:(AMapNaviMode)naviMode {
    NSLog(@"开始导航");
}

/**
 * @brief 实时导航到达目的地后的回调函数
 * @param driveManager 驾车导航管理类
 */
- (void)driveManagerOnArrivedDestination:(AMapNaviDriveManager *)driveManager {
    
}



#pragma mark - AMapNaviDriveViewDelegate
/**
 * @brief 导航界面关闭按钮点击时的回调函数
 * @param driveView 驾车导航界面
 */
- (void)driveViewCloseButtonClicked:(AMapNaviDriveView *)driveView {
    // 释放内存
    [_driveManager stopNavi];
    [_driveManager removeEventListener:self];
    [_driveManager removeDataRepresentative:_driveView];
    _driveView.delegate = nil;
    _driveManager = nil;
    [AMapNaviDriveManager destroyInstance];
    // 通知flutter
    [_channel invokeMethod:@"close" arguments:nil];
}




@end
